package co.fitstart.admin.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.BusinessException;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dynamic;
import com.demo2do.core.support.Page;

import co.fitstart.admin.dao.CourseRoundDao;
import co.fitstart.admin.dao.CourseScheduleDao;
import co.fitstart.admin.dao.StudentDao;
import co.fitstart.admin.dao.UserDao;
import co.fitstart.admin.dao.UserSourceDao;
import co.fitstart.admin.entity.search.SourceSearch;
import co.fitstart.admin.service.UserSourceService;
import co.fitstart.entity.course.CourseType;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.round.RoundStatus;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.course.schedule.ScheduleStatus;
import co.fitstart.entity.principal.Principal;
import co.fitstart.entity.site.Site;
import co.fitstart.entity.user.Student;
import co.fitstart.entity.user.User;
import co.fitstart.entity.user.UserSource;
import co.fitstart.entity.user.UserSourceRecord;
import co.fitstart.entity.user.UserSourceStatus;
import co.fitstart.entity.user.UserSourceType;

/**
 * 
 * @author mohanlan
 *
 */
@Service("userSourceService")
public class UserSourceServiceImpl extends DataServiceImpl<UserSource> implements UserSourceService {

	@Dynamic
	private UserDao userDao;

	@Dynamic
	private StudentDao studentDao;

	@Dynamic
	private CourseRoundDao courseRoundDao;

	@Dynamic
	private CourseScheduleDao courseScheduleDao;

	@Dynamic
	private UserSourceDao userSourceDao;

	@Autowired
	private GenericDaoSupport genericDaoSupport;

	@Override
	public UserSourceType loadSourceType(String name) {
		String sentence = "FROM UserSourceType WHERE disabled = false AND name = :name";
		return genericDaoSupport.searchForObject(sentence, "name", name, UserSourceType.class);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<UserSource> listSource(Date beginDate, Date endDate, Site site) {
		Map<String, Object> params = new HashMap<String, Object>();
		if (site == null) {
			String sentence = "FROM UserSource WHERE disabled = false AND occurDate >= :beginDate AND occurDate <= :endDate";
			params.put("beginDate", beginDate);
			params.put("endDate", endDate);

			return genericDaoSupport.searchForList(sentence, params);
		} else {
			String sentence = "FROM UserSource WHERE disabled = false AND occurDate >= :beginDate AND occurDate <= :endDate AND site = :site";
			params.put("beginDate", beginDate);
			params.put("endDate", endDate);
			params.put("beginDate", beginDate);
			params.put("site", site);

			return genericDaoSupport.searchForList(sentence, params);
		}
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<UserSource> listSource(Date beginDate, Date endDate, List<Site> sites) {
		
		Map<String, Object> params = new HashMap<String, Object>();
		if(CollectionUtils.isNotEmpty(sites)) {
			String sentence = "FROM UserSource WHERE disabled = false AND createTime >= :beginDate AND createTime <= :endDate AND site in (:sites)";
			params.put("beginDate", beginDate);
			params.put("endDate", endDate);
			params.put("sites", sites);
			
			return genericDaoSupport.searchForList(sentence, params);
		} else {
			String sentence = "FROM UserSource WHERE disabled = false AND createTime >= :beginDate AND createTime <= :endDate";
			params.put("beginDate", beginDate);
			params.put("endDate", endDate);

			return genericDaoSupport.searchForList(sentence, params);
		}
	}

	/*
	 * 
	 */
	@SuppressWarnings("unchecked")
	public List<UserSource> listSource(Site site, UserSourceStatus userSourceStatus) {

		String sentence = "FROM UserSource WHERE disabled = false AND site = :site";

		Map<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("site", site);

		return genericDaoSupport.searchForList(sentence, parameters);
	}

	/*
	 * 
	 */
	public List<UserSource> listSource(Site site, Page page, UserSourceStatus userSourceStatus) {

		List<UserSource> result = new ArrayList<UserSource>();

		if (site == null) {
			result = userSourceDao.listUserSource(userSourceStatus, page.getBeginIndex(), page.getMaxResultRecords());

		} else {
			result = userSourceDao.listUserSource(userSourceStatus, site, page.getBeginIndex(),
					page.getMaxResultRecords());
		}

		page.calculate(result.size());
		return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
	}

	/**
	 * 
	 */
	public List<UserSource> listSource(List<Site> sites, Page page, UserSourceStatus userSourceStatus) {

		List<UserSource> result = new ArrayList<UserSource>();
		result = userSourceDao.listUserSource(userSourceStatus, sites, page.getBeginIndex(),
				page.getMaxResultRecords());
		page.calculate(result.size());
		return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
	}

	/**
	 * 
	 */
	@SuppressWarnings("unchecked")
	public List<UserSource> search(SourceSearch sourceSearch, Page page) {

		List<UserSource> result = genericDaoSupport.searchForList(sourceSearch.buildSentenceTemplate(),
				sourceSearch.buildParameters(), page.getBeginIndex(), page.getMaxResultRecords());

		page.calculate(result.size());
		return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
	}

	@Override
	public UserSource load(String mobile) {
		return genericDaoSupport.searchForObject("FROM UserSource WHERE disabled = false AND mobile = :mobile",
				"mobile", mobile, UserSource.class);
	}

	/**
	 * 
	 */
	public void create(Date occurDate, Site site, String name, String mobile, String gender, String wechatNumber, String requirement,
			Long receiver, Long phoneReciver, Long userSourceType, String newSourceChannel) {

		if (site == null) {
			throw new BusinessException("门店不存在");
		}
		UserSource userSource = null;
		if(StringUtils.isNotEmpty(mobile)) {
			userSource = userSourceDao.load(mobile);
			if (userSource != null) {
				throw BusinessException.codeAndMessageOf("600", "渠道记录已存在，请新增回访！");
			}			
		}

		User user = null;
		if (org.apache.commons.lang3.StringUtils.isNotEmpty(mobile)) {

			user = userDao.load(mobile);
			if (user == null) {
				user = new User(mobile.trim(), name, false);
				genericDaoSupport.save(user);
			}
		}

		UserSourceType ruserSourceType = null;
		if (userSourceType == 0) {
			ruserSourceType = new UserSourceType();
			ruserSourceType.setDisabled(false);
			ruserSourceType.setName(newSourceChannel);
			ruserSourceType.setParent(new Long(6));
			genericDaoSupport.save(ruserSourceType);
		} else {
			ruserSourceType = genericDaoSupport.load(UserSourceType.class, userSourceType);
		}

		Principal previcer = genericDaoSupport.load(Principal.class, receiver);

		userSource = new UserSource(occurDate, name, mobile, gender, wechatNumber, requirement, site, previcer, null,
				ruserSourceType);
		userSource.setUserSourceStatus(UserSourceStatus.NOORDER);

		// 三大状态监测，是否到店，是否成单，在营结营续课
		if (StringUtils.isNotBlank(userSource.getMobile())) {
			Student student = studentDao.load(userSource.getMobile());
			if (student != null) {
				userSource = this.changeSourceType(student, userSource);
			}
		}

		genericDaoSupport.save(userSource);
	}

	@SuppressWarnings("unchecked")
	private UserSource changeSourceType(Student student, UserSource userSource) {

		// check if has on training course

		// 是否成单
		List<CourseRound> orderCourseRounds = courseRoundDao.listOrderMain(Arrays.asList(
				new CourseType[] { CourseType.INDIVIDUAL, CourseType.POSTURE, CourseType.SPECIAL, CourseType.YEAR }),
				Arrays.asList(new RoundStatus[] { RoundStatus.PREPARE, RoundStatus.READY, RoundStatus.HOLD,
						RoundStatus.EXPIRE, RoundStatus.ACTIVATE, RoundStatus.FINISH }),
				userSource.getMobile());
		if (org.apache.commons.collections.CollectionUtils.isNotEmpty(orderCourseRounds)) {
			userSource.setOrdered(true);
			userSource.setOrderedDate(orderCourseRounds.get(0).getCreateTime());
			userSource.setUserSourceStatus(UserSourceStatus.ORDERED);
		}

		// 是否到店，到店时间，教练
		CourseSchedule courseSchedule = courseScheduleDao.loadFirstFinishSchedule(student, ScheduleStatus.FINISH);
		if (courseSchedule != null) {
			userSource.setCoach(courseSchedule.getCoach());
			userSource.setVisitedDate(courseSchedule.getOccurDate());
			userSource.setVisited(true);
		}

		String sentence = "FROM CourseRound WHERE disabled = false AND course.experience = :experience AND courseStatus in (:status) AND student = :student";

		List<RoundStatus> statuses = new ArrayList<RoundStatus>();
		statuses.add(RoundStatus.PREPARE);
		statuses.add(RoundStatus.READY);
		statuses.add(RoundStatus.HOLD);

		Map<String, Object> parameters = new HashMap<>();
		parameters.put("student", student);
		parameters.put("status", statuses);
		parameters.put("experience", false);

		List<CourseRound> courseRounds = genericDaoSupport.searchForList(sentence, parameters);

		String sentence2 = "FROM CourseRound WHERE disabled = false AND course.experience = :experience AND courseStatus in (:status) AND student = :student";
		List<RoundStatus> statuses2 = new ArrayList<RoundStatus>();
		statuses2.add(RoundStatus.FINISH);
		statuses2.add(RoundStatus.FOREVEREXPIRE);
		Map<String, Object> parameters2 = new HashMap<>();
		parameters2.put("student", student);
		parameters2.put("status", statuses2);
		parameters2.put("experience", false);
		List<CourseRound> courseRounds2 = genericDaoSupport.searchForList(sentence2, parameters2);

		// 两个都不为空的情况下为在营续课
		if (org.apache.commons.collections.CollectionUtils.isNotEmpty(courseRounds)
				&& org.apache.commons.collections.CollectionUtils.isNotEmpty(courseRounds2)) {
			userSource.setUserSourceTypeName(userSource.getUserSourceType().getName());
			userSource.setOldUserSourceType(userSource.getUserSourceType());
			UserSourceType userSourceType = this.loadByName("在营续课");
			userSource.setUserSourceType(userSourceType);
			userSource.setUserSourceStatus(UserSourceStatus.ORDERED);
		// 在营为空的情况下为结营续课
		} else if (org.apache.commons.collections.CollectionUtils.isEmpty(courseRounds)
				&& org.apache.commons.collections.CollectionUtils.isNotEmpty(courseRounds2)) {
			userSource.setUserSourceTypeName(userSource.getUserSourceType().getName());
			userSource.setOldUserSourceType(userSource.getUserSourceType());
			UserSourceType userSourceType = this.loadByName("结营续课");
			userSource.setUserSourceType(userSourceType);
			userSource.setUserSourceStatus(UserSourceStatus.ORDERED);
		}

		return userSource;
	}

	private UserSourceType loadByName(String name) {
		String sentence2 = "FROM UserSourceType WHERE disabled = false AND name = :name";
		return genericDaoSupport.searchForObject(sentence2, "name", name, UserSourceType.class);
	}

	@Override
	public UserSourceRecord createRecord(Site site, UserSource userSource, String type, String description,
			String remark, Long receiver) {

		if (site == null) {
			throw new BusinessException("门店不存在");
		}

		if (userSource == null) {
			throw new BusinessException("渠道记录不存在！");
		}
		Principal previcer = genericDaoSupport.load(Principal.class, receiver);

		UserSourceRecord userSourceRecord = new UserSourceRecord(site, previcer, userSource, type, description, remark);
		genericDaoSupport.save(userSourceRecord);
		return userSourceRecord;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<UserSourceRecord> listRecords(UserSource userSource) {
		return genericDaoSupport.searchForList(
				"FROM UserSourceRecord WHERE disabled = false AND userSource = :userSource", "userSource", userSource);
	}

	@SuppressWarnings("unchecked")
	@Override
	public void refreshAllType() {
		UserSourceType userSourceType = this.loadByName("结营续课");
		UserSourceType userSourceType2 = this.loadByName("在营续课");
		List<UserSourceType> userSourceTypes = new ArrayList<UserSourceType>();
		userSourceTypes.add(userSourceType2);
		userSourceTypes.add(userSourceType);
		String sentence = "FROM UserSource WHERE disabled = false AND userSourceType not in (:userSourceTypes)";
		List<UserSource> userSources = genericDaoSupport.searchForList(sentence, "userSourceTypes", userSourceTypes);
		for (UserSource userSource : userSources) {
			if (StringUtils.isNotEmpty(userSource.getMobile())) {
				Student student = studentDao.load(userSource.getMobile());
				if (student != null) {
					this.changeSourceType(student, userSource);
					genericDaoSupport.update(userSource);
				}
			}
		}
	}

	@Override
	public void batchCreate(List<UserSource> userSources, Site site) {

		for (UserSource userSource : userSources) {
			userSource.setUserSourceStatus(UserSourceStatus.NOORDER);
			userSource.setSite(site);
			if (StringUtils.isNotEmpty(userSource.getMobile())) {
				UserSource exit = this.load(userSource.getMobile());
				if (exit != null) {
					continue;
				}

				// 是否到店，与教练
				List<CourseRound> courseRounds = courseRoundDao.listExperience(CourseType.INDIVIDUAL, new Long(4),
						Arrays.asList(new RoundStatus[] { RoundStatus.PREPARE, RoundStatus.READY, RoundStatus.HOLD,
								RoundStatus.EXPIRE, RoundStatus.ACTIVATE, RoundStatus.FINISH }),
						userSource.getMobile());
				if (org.apache.commons.collections.CollectionUtils.isNotEmpty(courseRounds)) {
					userSource.setCoach(courseRounds.get(0).getCoach());
					if (courseRounds.get(0).isFinish()) {
						userSource.setVisited(true);
						userSource.setVisitedDate(courseRounds.get(0).getSchedules().get(0).getOccurDate());
					}
				}

				// 是否成单
				List<CourseRound> orderCourseRounds = courseRoundDao.listOrderMain(
						Arrays.asList(new CourseType[] { CourseType.INDIVIDUAL, CourseType.POSTURE, CourseType.SPECIAL,
								CourseType.YEAR }),
						Arrays.asList(new RoundStatus[] { RoundStatus.PREPARE, RoundStatus.READY, RoundStatus.HOLD,
								RoundStatus.EXPIRE, RoundStatus.ACTIVATE, RoundStatus.FINISH }),
						userSource.getMobile());
				if (org.apache.commons.collections.CollectionUtils.isNotEmpty(orderCourseRounds)) {
					userSource.setOrdered(true);
					userSource.setUserSourceStatus(UserSourceStatus.ORDERED);
				}
			}

			genericDaoSupport.save(userSource);
		}

	}
}
